﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using esriUtil;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesRaster;

namespace ODM_Code.Code
{
    public class CheckProjectNAvTR
    {
        private string pathToAlternative1Results;
        private string fire1;
        private string period1;
        private string iter1;
        private string pathToAlternative2Results;
        private string fire2;
        private string period2;
        private string iter2;
        private List<string> rastersToCompare;
        private List<bool> useList;
        private string treatgridPath;
        private string treatshapePath;
        private bool useTreatedOnly;

        

        public CheckProjectNAvTR(string pathToAlternative1, string pathToAlternative2, string pathToTreatgrid)
        {
            this.pathToAlternative1Results = pathToAlternative1;
            this.pathToAlternative2Results = pathToAlternative2;
            this.treatgridPath = pathToTreatgrid;

            rastersToCompare = new List<string>();
            rastersToCompare.Add("arrivaltime");
            rastersToCompare.Add("nodeflamelength");
            rastersToCompare.Add("objvalues");
        }

        public void setFire1(string fire1) { this.fire1 = fire1; }
        public void setPeriod1(string period1) { this.period1 = period1; }
        public void setIter1(string iter1) { this.iter1 = iter1; }
        public void setFire2(string fire2) { this.fire2 = fire2; }
        public void setPeriod2(string period2) { this.period2 = period2; }
        public void setIter2(string iter2) { this.iter2 = iter2; }
        public void setUseTreated(bool use) { this.useTreatedOnly = use; }
        public void setTreatShapePath(string treatshapePath) { this.treatshapePath = treatshapePath; }

        private List<string> ParseCuttingUnits(string pathToOutIntFile)
        {
            StreamReader sr = new StreamReader(pathToOutIntFile);
            sr.ReadLine();

            List<string> retList = new List<string>();
            string line = "==========";
            string[] spl;
            while (!sr.EndOfStream) 
            {
                line = sr.ReadLine();
                if (line.Length < 2) { break; }
                spl = line.Split('\t');
                string cut_un = spl[0];
                string per = spl[3];
                if (!per.Equals("0"))
                {
                    retList.Add(cut_un);
                }
            }

            sr.Close();
            return retList;
        }

        private void createUseGrid(string pathToTreatgrid)
        {
            List<string> treatList = this.ParseCuttingUnits(pathToAlternative1Results + "\\Out_Int_RP_" + iter1 + ".txt");
            StreamReader sr = new StreamReader(pathToTreatgrid);
            sr.ReadLine();
            sr.ReadLine();
            sr.ReadLine();
            sr.ReadLine();
            sr.ReadLine();
            sr.ReadLine();

            List<bool> useList = new List<bool>();
            string line = "";
            string[] spl;
            while (!sr.EndOfStream)
            {
                line = sr.ReadLine();
                spl = line.Split(' ');
                foreach (string s in spl)
                {
                    bool use = false;
                    foreach (string t in treatList)
                    {
                        if (s.Equals(t)) { use = true; }
                    }
                    useList.Add(use);
                }
            }
            sr.Close();
            this.useList = useList;
        }

        public Dictionary<string, double[]> CompareRasters()
        {
            Dictionary<string, double[]> retDict = new Dictionary<string, double[]>();
            this.createUseGrid(treatgridPath);
            foreach (string ras in rastersToCompare)
            {
                string rasName1 = pathToAlternative1Results + "\\" + ras + iter1 + "_" + fire1 + "_" + period1 + ".txt";
                string rasName2 = pathToAlternative2Results + "\\" + ras + iter2 + "_" + fire2 + "_" + period2 + ".txt";

                double count = 0d;

                double ras1Sum;
                double ras1Avg;
                this.DoCompare(rasName1, out ras1Sum, out ras1Avg, out count);

                double ras2Sum;
                double ras2Avg;
                this.DoCompare(rasName2, out ras2Sum, out ras2Avg, out count);

                double sumDiff = ras1Sum - ras2Sum;
                double avgDiff = ras1Avg - ras2Avg;

                double[] retAry = new double[3];
                retAry[0] = sumDiff;
                retAry[1] = avgDiff;
                retAry[2] = count;
                retDict.Add(ras, retAry);
            }
            return retDict;
        }

        private void DoCompare(string rasterName, out double sum, out double average, out double count)
        {
            StreamReader sr = new StreamReader(rasterName);
            sr.ReadLine();
            sr.ReadLine();
            sr.ReadLine();
            sr.ReadLine();
            sr.ReadLine();
            string line = sr.ReadLine();
            string nodataStr = line.Substring(14);
            double nodata = double.Parse(nodataStr);

            sum = 0;
            count = 0;
            int lineNum = 0;

            while (!sr.EndOfStream)
            {
                line = sr.ReadLine();
                this.SumLine(line, nodata, ref sum, ref count, ref lineNum);
            }

            average = sum / count;
        }

        private void SumLine(string line, double nodata, ref double total, ref double count, ref int lineNum)
        {
            string[] spl = line.Split(' ');
            double temp;
            for (int i = 0; i < spl.Length - 1; i++)
            {
                string s = spl[i];
                bool use = useList[i + lineNum];
                temp = double.Parse(s);

                if (useTreatedOnly == true)
                {
                    if (temp == nodata || use == false)
                    {
                        continue;
                    }
                }
                else
                {
                    if (temp == nodata)
                    {
                        continue;
                    }
                }

                
                total += temp;
                count++;
            }
            lineNum += spl.Length;
        }

        public void RunPairedTTest()
        {
            rasterUtil ru = new rasterUtil();
            
            IRaster valuecatRaster = this.RemapTreatgridToValuecat(ref ru);

            foreach (string ras in rastersToCompare)
            {
                string rasName1 = pathToAlternative1Results + "\\" + ras + iter1 + "_" + fire1 + "_" + period1 + ".txt";
                string rasName2 = pathToAlternative2Results + "\\" + ras + iter2 + "_" + fire2 + "_" + period2 + ".txt";

                IRaster ras1 = ru.returnRaster(rasName1);
                IRaster ras2 = ru.returnRaster(rasName2);
                IRaster stackRaster = ru.compositeBandFunction(new IRaster[]{ras1, ras2});

                try
                {
                    esriUtil.Statistics.dataPrepPairedTTest pttest = new esriUtil.Statistics.dataPrepPairedTTest(valuecatRaster, stackRaster);
                    pttest.getReport();
                    pttest.ReportForm.Text += " for " + ras;
                    pttest.ReportForm.Width = 800;
                    pttest.ReportForm.Height = 300;
                    pttest.ReportForm.Refresh();
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Trace.WriteLine(ex.Message);
                }
                
            }
        }

        private IRaster RemapTreatgridToValuecat(ref rasterUtil ru)
        {
            IRaster treatRaster = ru.returnRaster(treatgridPath);
            IRemapFilter remFilter = this.CreateValuecatFilter();
            IRaster valueCatRaster = ru.calcRemapFunction(treatRaster, remFilter);
            return valueCatRaster;
        }

        private IRemapFilter CreateValuecatFilter()
        {
            geoDatabaseUtility geo = new geoDatabaseUtility();
            IFeatureClass treatShape = geo.returnFeatureClass(treatshapePath);

            ITable treatTable = (ITable)treatShape;
            ICursor curse = treatTable.Search(null, false);

            IFields allfields = curse.Fields;
            int valuecatField = allfields.FindField("VALUECAT");
            int ncutunitField = allfields.FindField("NCUT_UN_ID");

            IRemapFilter remFilter = new RemapFilterClass();

            IRow row = curse.NextRow();
            while (row != null)
            {
                double ncutunit = Convert.ToDouble(row.get_Value(ncutunitField));
                double valcat = Convert.ToDouble(row.get_Value(valuecatField));
                remFilter.AddClass(ncutunit, ncutunit + 1, valcat);
                row = curse.NextRow();
            }

            return remFilter;
        }


    }
}
